/*
 * Copyright (c) Hisilicon Technologies Co., Ltd. 2019-2019. All rights reserved.
 * Description: This file is used to display the results of adas processing.
 * Author:  HiMobileCam Reference Develop Team
 * Create: 2019/11/08
 */

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include "hi_gv_graphiccontext.h"
#include "hi_appcomm_util.h"
#include "hi_mapi_vproc.h"

#include "ui_common.h"

#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif
#endif /*  __cplusplus  */

typedef struct {
    HI_U32 startX;
    HI_U32 startY;
    HI_U32 endX;
    HI_U32 endY;
}UI_DRAW_Point;
typedef struct {
    HI_U32 screenWidth;
    HI_U32 screenHeight;
    HI_U32 adasWidth;
    HI_U32 adasHeight;
    HIGV_HANDLE wingGC;
}UI_DRAW_Ctx;

HI_VIDEOANALYSIS_AdasResult g_result;
UI_DRAW_Ctx g_drawCtx = {.screenWidth = 0,
                         .screenHeight = 0,
                         .adasWidth = 0,
                         .adasHeight = 0,
                         .wingGC = INVALID_HANDLE};

static HI_VOID PDT_UI_SwitchRatioCoordinate(UI_DRAW_Point* point)
{
    HI_U32 ratioHeight = g_drawCtx.screenWidth* g_drawCtx.adasHeight / g_drawCtx.adasWidth;
    if(g_drawCtx.screenHeight == ratioHeight) {
        return;
    }else if(g_drawCtx.screenHeight > ratioHeight) {
        point->startY += (g_drawCtx.screenHeight - ratioHeight) / 2U;
        point->endY   += (g_drawCtx.screenHeight - ratioHeight) / 2U;
    }else {
        point->startY -= (ratioHeight - g_drawCtx.screenHeight) / 2U;
        point->endY   -= (ratioHeight - g_drawCtx.screenHeight) / 2U;
    }
}

static HI_VOID PDT_UI_SwitchLDWCropCoordinate(const VPSS_CROP_INFO_S cropInfo, UI_DRAW_Point* point)
{
    HI_U32 showHeight = cropInfo.stCropRect.s32Y + cropInfo.stCropRect.u32Height;
    HI_FLOAT k = (HI_FLOAT)((HI_S32)point->endY - (HI_S32)point->startY) /
        ((HI_S32)point->endX - (HI_S32)point->startX);
    HI_FLOAT b = point->startY - k * point->startX;

    if(point->startY < cropInfo.stCropRect.s32Y) {
        point->startX = (HI_U32)((cropInfo.stCropRect.s32Y - b) / k);
        point->startY = 0;
    }else if(point->startY > showHeight) {
        point->startX = (HI_U32)((showHeight - b) / k);
        point->startY = cropInfo.stCropRect.u32Height;
    } else {
        point->startY -= cropInfo.stCropRect.s32Y;
    }
    if(point->endY < cropInfo.stCropRect.s32Y) {
        point->endY = 0;
        point->endX = (HI_U32)((cropInfo.stCropRect.s32Y - b) / k);
    }else if (point->endY > showHeight) {
        point->endY = cropInfo.stCropRect.u32Height;
        point->endX = (HI_U32)((showHeight - b) / k);
    }else {
        point->endY -= cropInfo.stCropRect.s32Y;
    }

}

static HI_VOID PDT_UI_SwitchFCWCropCoordinate(const VPSS_CROP_INFO_S cropInfo, UI_DRAW_Point* point)
{
    HI_U32 showHeight = cropInfo.stCropRect.s32Y + cropInfo.stCropRect.u32Height;
    if(point->startY < cropInfo.stCropRect.s32Y) {
        point->startY = 0;
    }else if(point->startY > showHeight) {
        point->startY = cropInfo.stCropRect.u32Height;
    }else {
        point->startY -= cropInfo.stCropRect.s32Y;
    }
    if(point->endY < cropInfo.stCropRect.s32Y) {
        point->endY = 0;
    }else if(point->endY > showHeight) {
        point->endY = cropInfo.stCropRect.u32Height;
    }else {
        point->endY -= cropInfo.stCropRect.s32Y;
    }
}
static HI_S32 PDT_UI_DrawLine(const UI_DRAW_Point point,HiAdasCapabiltyType type)
{
    HI_S32 ret;
    VPSS_CROP_INFO_S cropInfo = {0};
    UI_DRAW_Point newPoint;
    HI_U32 showHeight;
    HI_PDT_MEDIA_BIND_SRC_CFG_S dispCfg;
    HI_S32 camID = HI_PDT_STATEMNG_GetPreViewCamID();
    HI_PDT_PARAM_GetDispSrcByCamID(camID,&dispCfg);
    if(g_drawCtx.screenWidth == 0 || g_drawCtx.screenHeight == 0) {
        HI_MAPI_VPORT_ATTR_S vPortAttr = {0};
        ret = HI_MAPI_VPROC_GetPortAttr(dispCfg.ModHdl, dispCfg.ChnHdl, &vPortAttr);
        HI_APPCOMM_CHECK_RETURN(ret, HI_FAILURE);
        g_drawCtx.screenWidth  = vPortAttr.u32Width;
        g_drawCtx.screenHeight = vPortAttr.u32Height;

    }
    ret = HI_MAPI_VPROC_GetPortCrop(dispCfg.ModHdl, dispCfg.ChnHdl, &cropInfo);
    HI_APPCOMM_CHECK_RETURN_WITH_ERRINFO(ret, ret, "HI_PDT_MEDIA_GetCropInfo");
    showHeight = cropInfo.stCropRect.s32Y + cropInfo.stCropRect.u32Height;
    newPoint.startX = point.startX * g_drawCtx.screenWidth / g_drawCtx.adasWidth;
    newPoint.endX   = point.endX * g_drawCtx.screenWidth / g_drawCtx.adasWidth;
    newPoint.startY = point.startY * g_drawCtx.screenHeight / g_drawCtx.adasHeight;
    newPoint.endY   = point.endY * g_drawCtx.screenHeight / g_drawCtx.adasHeight;
    PDT_UI_SwitchRatioCoordinate(&newPoint);
    if((newPoint.startY < cropInfo.stCropRect.s32Y && newPoint.endY < cropInfo.stCropRect.s32Y) ||
        (newPoint.startY > showHeight && newPoint.endY > showHeight)) {
        MLOGD("dont need draw[%d][%d][%d]!\n", newPoint.startY, newPoint.endY, showHeight);
        return HI_SUCCESS;
    }
    if(type == HI_ADAS_CAP_LDW) {
        PDT_UI_SwitchLDWCropCoordinate(cropInfo, &newPoint);
    }else if(type == HI_ADAS_CAP_FCW) {
        PDT_UI_SwitchFCWCropCoordinate(cropInfo, &newPoint);
    }
    MLOGD("old:[%d][%d][%d][%d]\n",point.startX,point.startY,point.endX,point.endY);
    MLOGD("new:[%d][%d][%d][%d]\n",newPoint.startX,newPoint.startY,newPoint.endX,newPoint.endY);
    ret = HI_GV_GraphicContext_DrawLine(g_drawCtx.wingGC, newPoint.startX, newPoint.startY, newPoint.endX, newPoint.endY);
    PDT_UI_CHECK_RET_WITHOUT_RETURN(ret, "draw line ");
    return HI_SUCCESS;
}

static HI_S32 PDT_UI_DealLDWEvent(HiAdasAlgoLdwResult ldwResult)
{
    HI_U32 i, j;
    HI_S32 ret;
    UI_DRAW_Point lanePoint;
    if(ldwResult.warnType != HI_ADAS_LDW_BUTT) {
        ret = HI_GV_Widget_Hide(UI_ADAS_LDW_WARN);
        HI_APPCOMM_CHECK_RETURN(ret, ret);
    }else {
        ret = HI_GV_Widget_Show(UI_ADAS_LDW_WARN);
        HI_APPCOMM_CHECK_RETURN(ret, ret);
    }
    for(i = 0;i < ldwResult.laneNum; i++) {
        HiAdasLane *lane = &ldwResult.lanes[i];
        if(lane->pointsNum >= 2U) {
            MLOGD("lane num:%d,point num:%d\n",ldwResult.laneNum,lane->pointsNum);
            for(j = 0; (j+1) < lane->pointsNum; j++) {
                MLOGD("start:[%d][%d], end:[%d][%d]\n",
                    ldwResult.lanes[i].points[j].x,
                    ldwResult.lanes[i].points[j].y,
                    ldwResult.lanes[i].points[j+1].x,
                    ldwResult.lanes[i].points[j+1].y);
                memset_s(&lanePoint, sizeof(UI_DRAW_Point), 0x0, sizeof(UI_DRAW_Point));
                lanePoint.startX = ldwResult.lanes[i].points[j].x;
                lanePoint.startY = ldwResult.lanes[i].points[j].y;
                lanePoint.endX   = ldwResult.lanes[i].points[j+1].x;
                lanePoint.endY   = ldwResult.lanes[i].points[j+1].y;
                ret = PDT_UI_DrawLine(lanePoint, HI_ADAS_CAP_LDW);
                PDT_UI_CHECK_RET_WITHOUT_RETURN(ret, "Coordinate");
            }
        }
    }
    return HI_SUCCESS;
}

static HI_S32 PDT_UI_DealFCWEvent(HiAdasAlgoFcwResult fcwResult)
{
    HI_S32 ret;
    UI_DRAW_Point top;
    UI_DRAW_Point bottom;
    UI_DRAW_Point left;
    UI_DRAW_Point right;
    if(fcwResult.warnNum == 0) {
        ret = HI_GV_Widget_Hide(UI_ADAS_FCW_WARN);
        HI_APPCOMM_CHECK_RETURN(ret, ret);
    }else {
        ret = HI_GV_Widget_Show(UI_ADAS_FCW_WARN);
        HI_APPCOMM_CHECK_RETURN(ret, ret);
    }
    MLOGD("car num:%d\n",fcwResult.carNum);
    for(HI_U32 i = 0; i < fcwResult.carNum; i++) {
        memset_s(&top, sizeof(UI_DRAW_Point), 0x0, sizeof(UI_DRAW_Point));
        top.startX = fcwResult.carList[i].obstacle.bbox.x;
        top.startY = fcwResult.carList[i].obstacle.bbox.y;
        top.endX   = fcwResult.carList[i].obstacle.bbox.x + fcwResult.carList[i].obstacle.bbox.width;
        top.endY   = fcwResult.carList[i].obstacle.bbox.y;

        ret = PDT_UI_DrawLine(top, HI_ADAS_CAP_FCW);
        PDT_UI_CHECK_RET_WITHOUT_RETURN(ret, "PDT_UI_DrawLine");

        memset_s(&bottom, sizeof(UI_DRAW_Point), 0x0, sizeof(UI_DRAW_Point));
        bottom.startX = fcwResult.carList[i].obstacle.bbox.x;
        bottom.startY = fcwResult.carList[i].obstacle.bbox.y + fcwResult.carList[i].obstacle.bbox.height;
        bottom.endX   = fcwResult.carList[i].obstacle.bbox.x + fcwResult.carList[i].obstacle.bbox.width;
        bottom.endY   = fcwResult.carList[i].obstacle.bbox.y + fcwResult.carList[i].obstacle.bbox.height;
        ret = PDT_UI_DrawLine(bottom, HI_ADAS_CAP_FCW);
        PDT_UI_CHECK_RET_WITHOUT_RETURN(ret, "PDT_UI_DrawLine");

        memset_s(&left, sizeof(UI_DRAW_Point), 0x0, sizeof(UI_DRAW_Point));
        left.startX = fcwResult.carList[i].obstacle.bbox.x;
        left.startY = fcwResult.carList[i].obstacle.bbox.y;
        left.endX   = fcwResult.carList[i].obstacle.bbox.x;
        left.endY   = fcwResult.carList[i].obstacle.bbox.y + fcwResult.carList[i].obstacle.bbox.height;
        ret = PDT_UI_DrawLine(left, HI_ADAS_CAP_FCW);
        PDT_UI_CHECK_RET_WITHOUT_RETURN(ret, "PDT_UI_DrawLine");

        memset_s(&right, sizeof(UI_DRAW_Point), 0x0, sizeof(UI_DRAW_Point));
        right.startX = fcwResult.carList[i].obstacle.bbox.x + fcwResult.carList[i].obstacle.bbox.width;
        right.startY = fcwResult.carList[i].obstacle.bbox.y;
        right.endX   = fcwResult.carList[i].obstacle.bbox.x + fcwResult.carList[i].obstacle.bbox.width;
        right.endY   = fcwResult.carList[i].obstacle.bbox.y + fcwResult.carList[i].obstacle.bbox.height;
        ret = PDT_UI_DrawLine(right, HI_ADAS_CAP_FCW);
        PDT_UI_CHECK_RET_WITHOUT_RETURN(ret, "PDT_UI_DrawLine");
    }
    return HI_SUCCESS;
}

static HI_S32 PDT_UI_DealFCREvent(HiAdasAlgoFcrResult fcrResult)
{
    HI_S32 ret;
    if(fcrResult.isFrontCarStart == HI_TRUE) {
        ret = HI_GV_Widget_Show(UI_ADAS_FCR_WARN);
        HI_APPCOMM_CHECK_RETURN(ret, ret);
    }else {
        ret = HI_GV_Widget_Hide(UI_ADAS_FCR_WARN);
        HI_APPCOMM_CHECK_RETURN(ret, ret);
    }
    return HI_SUCCESS;
}
static HI_S32 PDT_UI_DRAW_DealAdasEvent(HiAdasAlgoProcessResult* result)
{
    HI_S32 ret;
    for(HI_U32 i = 0; i < result->resultNum; i++) {
        switch(result->resultList[i].type) {
            case HI_ADAS_CAP_LDW:
                ret = HI_GV_GraphicContext_SetFgColor(g_drawCtx.wingGC, 0xFFFF0000);
                HI_APPCOMM_CHECK_RETURN_WITH_ERRINFO(ret, ret, "HI_GV_GraphicContext_SetFgColor");
                ret = PDT_UI_DealLDWEvent(result->resultList[i].result.ldwResult);
                HI_APPCOMM_CHECK_RETURN_WITH_ERRINFO(ret, ret, "PDT_UI_DealLDWEvent");
                break;
            case HI_ADAS_CAP_FCW:
                ret = HI_GV_GraphicContext_SetFgColor(g_drawCtx.wingGC, 0xFFFFFF00);
                HI_APPCOMM_CHECK_RETURN_WITH_ERRINFO(ret, ret, "HI_GV_GraphicContext_SetFgColor");
                ret = PDT_UI_DealFCWEvent(result->resultList[i].result.fcwResult);
                HI_APPCOMM_CHECK_RETURN_WITH_ERRINFO(ret, ret, "PDT_UI_DealFCWEvent");
                break;
            case HI_ADAS_CAP_FCR:
                ret = PDT_UI_DealFCREvent(result->resultList[i].result.fcrResult);
                HI_APPCOMM_CHECK_RETURN_WITH_ERRINFO(ret, ret, "PDT_UI_DealFCREvent");
                break;
            default:
                MLOGW("not support[0x%x]!\n",result->resultList[i].type);
                break;
        }
    }
    return HI_SUCCESS;
}
static HI_S32 PDT_UI_DRAW_AdasResult(HI_VIDEOANALYSIS_AdasResult* result)
{
    HI_RECT Rect;
    Rect.x = 0;
    Rect.y = 0;
    Rect.w = XML_LAYOUT_WIDTH;
    Rect.h = XML_LAYOUT_HEIGHT;
    HI_S32 ret = HI_GV_GraphicContext_Create(UI_DRAW_GROUP, &g_drawCtx.wingGC);
    HI_APPCOMM_CHECK_RETURN_WITH_ERRINFO(ret, ret, "HI_GV_GraphicContext_Create");
    ret = HI_GV_GraphicContext_Begin(g_drawCtx.wingGC);
    HI_APPCOMM_CHECK_RETURN_WITH_ERRINFO(ret, ret, "HI_GV_GraphicContext_Begin");
    ret = HI_GV_GraphicContext_AddClipRect(g_drawCtx.wingGC, &Rect);
    HI_APPCOMM_CHECK_RETURN_WITH_ERRINFO(ret, ret, "HI_GV_GraphicContext_AddClipRect");
    ret = HI_GV_GraphicContext_SetFont(g_drawCtx.wingGC, FONT22);
    HI_APPCOMM_CHECK_RETURN_WITH_ERRINFO(ret, ret, "HI_GV_GraphicContext_SetFont");
    MLOGD("result num:%d\n",result->result.resultNum);
    ret = PDT_UI_DRAW_DealAdasEvent(&result->result);
    PDT_UI_CHECK_RET_WITHOUT_RETURN(ret, "PDT_UI_DRAW_DealAdasEvent");
    ret = HI_GV_GraphicContext_End(g_drawCtx.wingGC);
    PDT_UI_CHECK_RET_WITHOUT_RETURN(ret, "HI_GV_GraphicContext_End");

    if (g_drawCtx.wingGC) {
        ret = HI_GV_GraphicContext_Destroy(g_drawCtx.wingGC);
        PDT_UI_CHECK_RET_WITHOUT_RETURN(ret, "HI_GV_GraphicContext_Destroy");
        g_drawCtx.wingGC = INVALID_HANDLE;
    }
    ret = HI_GV_Widget_Paint(UI_DRAW_GROUP, NULL);
    PDT_UI_CHECK_RET_WITHOUT_RETURN(ret, "HI_GV_Widget_Paint");
    return HI_SUCCESS;
}

HI_S32 PDT_UI_DRAW_OnShow(HIGV_HANDLE widgetHdl, HI_PARAM wParam, HI_PARAM lParam)
{
    MLOGI("\n");

    HI_S32 ret = HI_GV_Widget_Hide(UI_ADAS_FCW_WARN);
    HI_APPCOMM_CHECK_RETURN(ret, HI_FAILURE);
    ret = HI_GV_Widget_Hide(UI_ADAS_FCR_WARN);
    HI_APPCOMM_CHECK_RETURN(ret, HI_FAILURE);
    ret = HI_GV_Widget_Hide(UI_ADAS_LDW_WARN);
    HI_APPCOMM_CHECK_RETURN(ret, HI_FAILURE);
    return HIGV_PROC_GOON;
}

HI_S32 PDT_UI_DRAW_OnHide(HIGV_HANDLE widgetHdl, HI_PARAM wParam, HI_PARAM lParam)
{
    MLOGD("\n");
    return HIGV_PROC_GOON;
}

HI_S32 PDT_UI_DRAW_OnKeyDown(HIGV_HANDLE WidgetHdl, HI_PARAM wParam, HI_PARAM lParam)
{
    return HIGV_PROC_GOON;
}

HI_S32 PDT_UI_DRAW_OnTimer(HIGV_HANDLE widgetHdl, HI_PARAM wParam, HI_PARAM lParam)
{
    return HIGV_PROC_GOON;
}

HI_S32 PDT_UI_DRAW_OnEvent(HIGV_HANDLE widgetHdl, HI_PARAM wParam, HI_PARAM lParam)
{
    MLOGD("wParam: %#lx, lParam = %#lx\n", (HI_UL)wParam, (HI_UL)lParam);
    HI_VIDEOANALYSIS_AdasResult* event = (HI_VIDEOANALYSIS_AdasResult*)lParam;

    if(g_drawCtx.adasWidth == 0 || g_drawCtx.adasHeight == 0) {
        g_drawCtx.adasWidth = event->width;
        g_drawCtx.adasHeight = event->height;
    }
    HI_S32 ret = HI_GV_Widget_Show(UI_DRAW_GROUP);
    HI_APPCOMM_CHECK_RETURN_WITH_ERRINFO(ret, ret, "HI_GV_Widget_Show");
    ret = PDT_UI_DRAW_AdasResult(event);
    HI_APPCOMM_CHECK_RETURN_WITH_ERRINFO(ret, ret, "PDT_UI_DRAW_AdasResult");

    return HIGV_PROC_GOON;
}

HI_S32 PDT_UI_DRAW_OnGestureTap(HIGV_HANDLE WidgetHdl, HI_PARAM wParam, HI_PARAM lParam)
{
    MLOGI("\n");
    return HIGV_PROC_GOON;
}

HI_S32 PDT_UI_DRAW_OnGestureFling(HIGV_HANDLE WidgetHdl, HI_PARAM wParam, HI_PARAM lParam)
{
    MLOGI("\n");
    return HIGV_PROC_GOON;
}

HI_S32 PDT_UI_GetADASAnalysisResult(HI_VIDEOANALYSIS_AdasResult* result, HI_VOID* privData)
{
    HI_S32 ret;
    if(result->result.resultNum == 0) {
        MLOGD("no event!\n");
        return HI_SUCCESS;
    }
    ret = memcpy_s(&g_result, sizeof(HI_VIDEOANALYSIS_AdasResult), result, sizeof(HI_VIDEOANALYSIS_AdasResult));
    HI_APPCOMM_CHECK_RETURN_WITH_ERRINFO(ret, ret, "memcpy_s");

    if(HI_GV_Widget_IsShow(UI_DRAW_WINDOW) && PDT_UI_HOME_GetHomePageStatus() == HI_TRUE) {
        ret = HI_GV_Widget_Hide(UI_DRAW_GROUP);
        HI_APPCOMM_CHECK_RETURN_WITH_ERRINFO(ret, ret, "HI_GV_Widget_Hide");
        ret = HI_GV_Msg_SendAsyncWithData(UI_DRAW_WINDOW, HIGV_MSG_EVENT, (HI_VOID*)&g_result, sizeof(HI_VIDEOANALYSIS_AdasResult));
        HI_APPCOMM_CHECK_RETURN_WITH_ERRINFO(ret, ret, "SendAsyncWithData");
    }
    return HI_SUCCESS;
}

#ifdef __cplusplus
#if __cplusplus
}
#endif
#endif /*  __cplusplus  */

